<template>
  <div class="wangeditor">
    <toolbar class="toolbar" :editor="editorRef" :default-config="toolbarConfig" :mode="mode" />
    <editor v-model="valueHtml" class="editor" :default-config="editorConfig" :mode="mode" @on-created="onCreated" />
  </div>
</template>

<script setup lang="ts">
import '@wangeditor/editor/dist/css/style.css';

import { Editor, Toolbar } from '@wangeditor/editor-for-vue';
import axios from 'axios';
import CryptoJS from 'crypto-js';
import { onBeforeUnmount, shallowRef } from 'vue';

import { request } from '@/utils/request';

const props = defineProps({
  readonly: {
    type: Boolean,
    default: false,
  },
});

const mode = 'default';

const editorRef = shallowRef();

const valueHtml = defineModel('value', { type: String });

const toolbarConfig = {};

const generateFileName = async (file: File) => {
  const data = await file.arrayBuffer();
  const wordArray = CryptoJS.lib.WordArray.create(data);
  const sha256 = CryptoJS.SHA256(wordArray).toString();
  const ext = file.name.substring(file.name.lastIndexOf('.'));
  return `${sha256}${ext}`;
};

const uploadFile = async (file: File) => {
  try {
    const postObjectParams = await request.get({
      url: '/infra/file/post-object-params',
    });

    const fileName = await generateFileName(file);

    const formData = new FormData();
    formData.append('success_action_status', '200');
    formData.append('policy', postObjectParams.policy);
    formData.append('x-oss-signature', postObjectParams.signature);
    formData.append('x-oss-signature-version', postObjectParams.version);
    formData.append('x-oss-credential', postObjectParams.credential);
    formData.append('x-oss-date', postObjectParams.ossdate);
    formData.append('key', `${postObjectParams.dir}${fileName}`);
    formData.append('x-oss-security-token', postObjectParams.token);
    formData.append('file', file);

    await axios.post(postObjectParams.host, formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    });

    const url = `${postObjectParams.host}/${postObjectParams.dir}${fileName}`;

    return url;
  } catch (error) {
    console.error(error);
  }
  return '';
};

const customUploadImage = async (file: File, insertFn: (url: string, alt: string, href: string) => void) => {
  try {
    const url = await uploadFile(file);
    insertFn(url, file.name, url);
  } catch (error) {
    console.error(error);
  }
};

const customUploadVideo = async (file: File, insertFn: (url: string) => void) => {
  try {
    const url = await uploadFile(file);
    insertFn(url);
  } catch (error) {
    console.error(error);
  }
};

const editorConfig = {
  readOnly: props.readonly,
  MENU_CONF: {
    uploadImage: {
      customUpload: customUploadImage,
    },
    uploadVideo: {
      customUpload: customUploadVideo,
    },
  },
};

const onCreated = (editor: any) => {
  editorRef.value = editor;
};

onBeforeUnmount(() => {
  const editor = editorRef.value;
  if (editor == null) return;
  editor.destroy();
});
</script>

<style lang="less" scoped>
.wangeditor {
  width: 100%;
  border: 1px solid #ccc;
  z-index: 31;

  .toolbar {
    border-bottom: 1px solid #ccc;
  }

  .editor {
    height: 500px !important;
    overflow-y: hidden;
  }
}

</style>
